// -*- coding: utf-8 -*-

#include <iostream>
#include <fstream>
#include <string>
#include <gaol/gaol>

#include "elisa/elisa.h"

#ifdef _WIN32
#include <crtdbg.h>
#endif

#include "Benchmarks.h"
#include "Bird.h"
#include "Circle.h"
#include "Simple.h"
#include "CircSin.h"
#include "Falling.h"
#include "Falling1.h"
#include "Horn.h"
#include "Taylor.h"
#include "Pentagram.h"

#define MAX_SOLS 256
#define TEST(NAME) test<NAME>(#NAME)

using namespace std;
using namespace elisa;

template <class T>
void test(const char* name) {
	cout << name << endl;

	elisa::Clock time;
	time.start();

	T modeler;
	Model & model = modeler.model();
	IntervalSolver solver(model);

	while (solver.next()) 
	{
		if(solver.numSolutions() > MAX_SOLS) { // 暴走防止
			cout << "Too many solutions. stop solving." << endl;
			break;
		}

		cout << "Solution " << solver.numSolutions() << endl;
		modeler.print();
	}

	time.stop();

	if (!solver.numSolutions()) 
		cout << "NO SOLUTION" << endl;
	else 
		cout << solver.numSolutions() << " solution(s)" << endl;

#ifdef ELISA_PROFILE
	cout << "split:\t" << solver.numSplit() << endl;
	cout << "boxes:\t" << solver.numProcessedBoxes() << endl;
	cout << "reduce(hull):\t" << HullReduction::NumCall << endl;
	cout << "reduce(box):\t"  << BoxReduction::NumCall << endl;
#endif

	cout << "time: " << time << endl;
	cout << endl;
}

int main(int argc, char *argv[])
{
	elisa::init();

	//elisa::useHC4();
	//elisa::useBC3();
	elisa::useBC5();
	//elisa::useBCNewton(); 

	double p(1.0e-12);
	if (argc == 2) {
		istringstream iss(argv[1]);
		iss >> p;
	}

	RealVar::SetPrecision(p);
	Interval::SetOutputDigits(20);

	//TEST(Abc);
	//TEST(Bird);
	//TEST(Caprasse);
	TEST(Chemistry1);
	//TEST(Chemistry2);
	//TEST(Cyclohexane);
	//TEST(Enfant1); // 求解時間長い
	//TEST(Enfant2);
	//TEST(Filter1);
	//TEST(Floudas);
	//TEST(Floudas2);
	//TEST(Goughstewart);
	//TEST(Kinematics1);
	//TEST(Kinematics2);
	//TEST(Kinematics3);
	//TEST(Min); // 求解不可
	//TEST(Quadratic);
	//TEST(Transistor);
	//TEST(Wilkinson);
	//TEST(Simple);
	//TEST(CircSin);
	//TEST(Falling);
	//TEST(Horn);
	//TEST(Taylor);
	//TEST(Robot);
	//TEST(Pentagram);

	elisa::dismiss();

	return EXIT_SUCCESS;
}
